/***************************************************/
/**				task.h by doom119				   */
/**					April, 2010					   */
/***************************************************/
#ifndef _TASK_H_
#define _TASK_H_

#include "descriptor.h"

#define NR_TASKS 64

#define TASK_RUNNING 0
#define TASK_INTERUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4

#define LAST_TASK task[NR_TASKS-1]
#define FIRST_TASK task[0]

struct tss
{
	long back_link;
	long esp0;
	long ss0;
	long esp1;
	long ss1;
	long esp2;
	long ss2;
	long cr3;
	long eip;
	long eflags;
	long eax, ecx, edx, ebx;
	long esp;
	long ebp;
	long esi;
	long edi;
	long es;
	long cs;
	long ss;
	long ds;
	long fs;
	long gs;
	long ldt; //ldt selector, not descriptor
	long trace_bitmap;
	//struct i387_struct i387;
};

struct task
{
	long state;
	long counter;
	long priority;
	long signal;
	long blocked;

	unsigned long start_code, end_code, end_data, brk, start_stack;
	long pid, father, pgrp;
	unsigned short uid, euid, suid;
	unsigned short gid, egid, sgid;
	long utime, stime;

	struct descriptor ldt[3];
	struct tss tss;
};

extern struct task *current;
extern struct task *task[NR_TASKS];

#define FIRST_TSS_ENTRY 4
#define FIRST_LDT_ENTRY 5

#define _TSS(n) ((((unsigned long)n) << 4) + (FIRST_TSS_ENTRY << 3))
#define _LDT(n) ((((unsigned long)n) << 4) + (FIRST_LDT_ENTRY << 3))


#define _set_tss_ldt_desc(n, addr, type) \
	__asm__("movw $104, %1\n\t" \
			"movw %%ax, %2\n\t" \
			"rorl $16, %%eax\n\t" \
			"movb %%al, %3\n\t" \
			"movb $" type ", %4\n\t" \
			"movb $0, %5\n\t" \
			"movb %%ah, %6\n\t" \
			::"a"(addr), "m"(*(n)), "m"(*(n+2)), \
			"m"(*(n+4)), "m"(*(n+5)), "m"(*(n+6)), "m"(*(n+7))\
		   )

#define set_tss_desc(n, addr) \
	_set_tss_ldt_desc(((char*)(n)), addr, "0x89")

#define set_ldt_desc(n, addr) \
	_set_tss_ldt_desc(((char*)(n)), addr, "0x82")

#define switch_to(n) {\
	struct {long a, b;} __tmp; \
	__asm__ ("cmpl %%ecx, current\n\t" \
			"je 1f\n\t" \
			"movw %%dx, %1\n\t" \
			"xchgl %%ecx, current\n\t" \
			"ljmp *%0\n\t" \
			"1:" \
			::"m"(*&__tmp.a), "m"(*&__tmp.b), \
			"d"(_TSS(n)), "c"((long)task[n])); \
}

#define ltr(n) \
	__asm__("ltr %%ax\n\t" \
			::"a"(_TSS(n)))
#define lldt(n) \
	__asm__("lldt %%ax\n\t" \
			::"a"(_LDT(n)))

#endif
